package com.zhou.controller;

import com.alibaba.fastjson.JSON;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.util.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cglib.core.Local;
import org.springframework.data.redis.connection.stream.StreamRecords;
import org.springframework.data.redis.connection.stream.StringRecord;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Array;
import java.time.DayOfWeek;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 打印日志的测试
 */

@RestController
public class Log4j2Controller {
     private static final Logger LOGGER = LoggerFactory.getLogger(Log4j2Controller.class);
    /**
     * 日志级别
     * OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL
     */
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private RedisTemplate<String,Object> redisTemplate;

    @Autowired
    private RedisLock redisLock;

    @RequestMapping("/printLog")
    public String printLog (String lock, String client, HttpServletRequest request){

        LOGGER.error("ERROR 级别日志");
        LOGGER.warn("WARN 级别日志");
        LOGGER.info("INFO 级别日志");
        LOGGER.debug("DEBUG 级别日志");
        LOGGER.trace("TRACE 级别日志");

//        Boolean aBoolean = stringRedisTemplate.opsForValue().setIfAbsent("lock", "client", 3000, TimeUnit.SECONDS);

        Boolean b = redisLock.tryLock("lock1", "client", 3000);
        LOGGER.info(b.toString());
        return "success" ;
    }


    /**
     * 用redis中的set数据结构模拟抽奖的功能
     *
     * 因为set数据结构里面的数据不是按照顺序进行排序的，所以随机pop是随机一个数字
     */
    @RequestMapping("set")
    public int redisSet() {
        // 将数据放到redis中
        depositValue();
        String string = redisTemplate.opsForSet().pop("pop_user").toString();
        LOGGER.info("幸运儿是：{}",string);
        return Integer.parseInt(string);
    }

    private void depositValue() {
        // 初始化先把员工放进redis中的容器当中
        List<Integer> integers = initUser();
        Boolean aBoolean = redisTemplate.hasKey("pop_user");
        if (!aBoolean){
            integers.forEach(data -> redisTemplate.opsForSet().add("pop_user",data.toString()));
        }
    }

    /**
     * 初始化员工，用Integer代替员工实体类
     * 模拟100个员工进行抽奖
     * @return
     */
    private static List<Integer> initUser() {
        // 因为我确定是100个人，所以直接给集合一个初始化100，节约内存的消耗
        List<Integer> list = new ArrayList<>(100);
        for (int i = 0; i < 100; i++) {
            list.add(i+1);
        }
        return list;
    }



    /**
     * 测试reids中的list数据结构
     */
    @RequestMapping("leftpush")
    public void add() {
//        redisTemplate.opsForList().leftPush("zhou","zhou");
        Object zhou = redisTemplate.opsForList().rightPop("zhou");
    }


    private void sendStreamRecord(String streamKey, String data) {
        Map<String, String> map = Collections.singletonMap("data", data);
        // 创建消息记录, 以及指定stream
        StringRecord stringRecord = StreamRecords
                .string(map)
                .withStreamKey(streamKey);
        redisTemplate.opsForStream().add(stringRecord);
    }
    /**
     * 利用redis做计数器
     * 可以处理业务上面的的一些访问次数之类的
     * 例如：文章的点赞数，阅读量，允许有一点的延迟效果，先保存到redis中，然后在同步到数据库当中
     */
    @RequestMapping("hello")
    public void count() {
        /**
         * 判断是否到达次数
         */
        Boolean aBoolean = invokeExceededTimes("time_key2",1,3);
        if (aBoolean) {
            LOGGER.info("可以访问");
        }else {
            LOGGER.info("请求次数达标了");
        }
    }

    /**
     * 判断同一个key在规定时间内访问次数是否到达了最高值
     * @param key   键
     * @param days  时间
     * @param count 一定时间内的访问次数
     * @return
     */
    public Boolean invokeExceededTimes(String key, int days, int count) {

        LOGGER.info("key值:{}",key);
        // 判断在redis中是否有key值
        Boolean redisKey = stringRedisTemplate.hasKey(key);
        if (redisKey) {
            // 获取key所对应的value
            Integer hasKey =Integer.parseInt(stringRedisTemplate.opsForValue().get(key));
            if (hasKey >= count) {
                return false;
            }
            // 对value进行加1操作
            stringRedisTemplate.opsForValue().increment(key,1);
            return true;
        }else {
            // 如果没有key值，对他进行添加到redis中
            stringRedisTemplate.opsForValue().set(key,"1",days,TimeUnit.DAYS);
        }
        return true;
    }

    @RequestMapping("mapTest")
    public void mapTest() {
        int dayOfYear = LocalDateTime.now().getDayOfYear();
        int dayOfMonth = LocalDateTime.now().getDayOfMonth();
        DayOfWeek dayOfWeek = LocalDateTime.now().getDayOfWeek();
        LOGGER.info(dayOfMonth + ":" + dayOfYear + ":" + dayOfWeek.toString());
        Map<String,Object> map = new HashMap<>(16);
        map.put("zhou","12");
        map.put("da","13");
        map.put("tou","14");
        map.forEach((k,v) -> {
            LOGGER.info(k + ":" + v);
        });
    }


}
